﻿// <copyright file="AxisAngleRotation3D.cs" company="Axelerate Solutions S.A.">
// Copyright (c) Axelerate Solutions S.A.  All rights reserved.
// </copyright>

namespace Axelerate.Silverlight3D.Media.Media3D
{
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    /// <summary>
    /// File name: AxisAngleRotation3D.cs
    /// Company: Axelerate Solutions S.A.
    /// Created By: Daniel Rojas
    /// Created Date: 10/09/2008 16:16:00 h.
    /// Description: Represents a 3-D rotation of a specified angle about a specified axis.
    ///   <Modifications>
    ///   </Modifications>
    /// </summary>
    public sealed class AxisAngleRotation3D : Rotation3D
    {
        #region Fields
        /// <summary>
        /// Identifies the Angle dependency property.
        /// </summary>
        public static readonly DependencyProperty AngleProperty =
                    DependencyProperty.Register(
                          "Angle",
                          typeof(double),
                          typeof(AxisAngleRotation3D),
                          new PropertyMetadata(OnAnglePropertyChanged));

        /// <summary>
        /// Identifies the Axis dependency property.
        /// </summary>
        public static readonly DependencyProperty AxisProperty =
                    DependencyProperty.Register(
                          "Axis",
                          typeof(Vector3D),
                          typeof(AxisAngleRotation3D),
                          new PropertyMetadata(OnAxisPropertyChanged));

        private Quaternion _cachedQuaternionValue;

        #endregion

        #region Properties
        
        /// <summary>
        /// Gets or sets the angle of a 3-D rotation, in degrees. This is a dependency property. 
        /// </summary>
        public double Angle
        {
            get
            {

                return (double)this.GetValue(AngleProperty);
            }
            set
            {
                this.SetValue(AngleProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the axis of a 3-D rotation. This is a dependency property.
        /// </summary>
        public Vector3D Axis
        {
            get
            {

                return (Vector3D)this.GetValue(AxisProperty);
            }
            set
            {
                this.SetValue(AxisProperty, value);
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Creates an instance of a 3-D rotation.
        /// </summary>
        public AxisAngleRotation3D() : base()
        {
            this._cachedQuaternionValue = Quaternion.Identity;
        }

        /// <summary>
        /// Creates an instance of a 3-D rotation using the specified axis and angle.
        /// </summary>
        /// <param name="axis">Vector3D that specifies the axis around which to rotate.</param>
        /// <param name="angle">Double that specifies the angle of rotation, in degrees.</param>
        public AxisAngleRotation3D(Vector3D axis, double angle)
        {
            this.Axis = axis;
            this.Angle = angle;
        }
        #endregion

        #region Methods
        /// <summary>
        /// Raise the Angle changed event
        /// </summary>
        /// <param name="d">DependencyObject owner of the property</param>
        /// <param name="e">DependencyPropertyChangedEventArgs with the necesary information</param>
        private static void OnAnglePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((AxisAngleRotation3D)d)._cachedQuaternionValue  = new Quaternion(((AxisAngleRotation3D)d).Axis,  (double)e.NewValue);
            ((AxisAngleRotation3D)d).NotifyPropertyChanged("Angle");
        }
        
        /// <summary>
        /// Raise the Axis changed event
        /// </summary>
        /// <param name="d">DependencyObject owner of the property</param>
        /// <param name="e">DependencyPropertyChangedEventArgs with the necesary information</param>
        private static void OnAxisPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((AxisAngleRotation3D)d)._cachedQuaternionValue = new Quaternion((Vector3D)e.NewValue, ((AxisAngleRotation3D)d).Angle);
            ((AxisAngleRotation3D)d).NotifyPropertyChanged("Axis");
        }
        #endregion

        /// <summary>
        /// Internal property used to retrieve the equivalent quaternion rotation
        /// </summary>
        internal override Quaternion InternalQuaternion
        {
            get
            {
                return this._cachedQuaternionValue;
            }
        }
    }
}
